#pragma once
#include "PThread.hpp"
#include "guardLock.hpp"
#include "logMessage.hpp"
#include <iostream>
#include <vector>
#include <queue>
#include <mutex>
using namespace threadNs;

const int numthread = 10;

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *threadpool, std::string tname) : _threadpool(threadpool), _tname(tname) {}
    ThreadPool<T> *_threadpool;
    std::string _tname;
};

template <class T>
class ThreadPool
{
private:
    // 这里是静态成员函数，没有this指针，是不能够访问ThreadPool变量的
    static void *handlerTask(void *args)
    {
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args); // 转化为ThreadData对象
        while (true)
        {
            T t;
            // 检测task_queue
            {
                MutexGuard lock(td->_threadpool->getGuardLock()); // 同样使用RAII方法构建锁
                while (td->_threadpool->queueisempty())
                {
                    td->_threadpool->pthreadwait();
                }
                // 弹出任务并执行
                t = td->_threadpool->pop();
            }
            //std::cout << td->_tname << "正在执行任务....任务是" << t() << std::endl; // 执行任务可以在锁外面并发的执行
            t();
        }
        delete td;
        return nullptr;
    }

public:
    pthread_mutex_t *getGuardLock() { return &_mutex; } // 采用RAII的形式定义锁，在创建的时候，加锁，在变量生命周期结束的时候，解锁
    void lockqueue() { pthread_mutex_lock(&_mutex); }
    void unlockqueue() { pthread_mutex_unlock(&_mutex); }
    bool queueisempty() { return _task_queue.empty(); }
    void pthreadwait() { pthread_cond_wait(&_cond, &_mutex); }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    } // 默认队列里面不是空的
public:
    ThreadPool() {}
    ThreadPool(const int &num = numthread) : _num(num)
    {
        // 对锁进行初始化
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(new Thread());
        }
    }

    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *_this = new ThreadData<T>(this, t->threadName());
            t->start(handlerTask, _this);
            //std::cout << t->threadName() << "start ..." << std::endl;
            debugLog(DEBUG,"%d is running...",t->threadName());
        }
    }

    void push(const T &in)
    {
        // push任务的时候需要加锁
        MutexGuard lock(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond); // 让等待的队列开始运行
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);

        for (const auto &t : _threads)
        {
            delete t;
        }
    }

    static ThreadPool<T> *getInstace()
    {
        if (tp == nullptr)
            {
                _singlelock.lock();
                if (tp == nullptr)
                    tp = new ThreadPool<T>(numthread);
                _singlelock.unlock();
            }
        return tp;
    }

    void operator=(const ThreadPool&) = delete;
    ThreadPool(const ThreadPool &)    = delete;

    private : 
    int _num; // 控制有几个线程
    std::vector<Thread *> _threads;
    std::queue<T> _task_queue; // 存访任务
    pthread_mutex_t _mutex;    // 定义一把锁
    pthread_cond_t _cond;      // 定义一个信号量

    // 构建一个单例模式,一个类只能有一个对象
    static ThreadPool<T> *tp;
    static std::mutex _singlelock;
};
template <class T>
ThreadPool<T> *ThreadPool<T>::tp = nullptr;   //只有定义了，模板才会实例化
template <class T>
std::mutex ThreadPool<T>::_singlelock;